/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jmodcog2.base;

import com.amd.aparapi.Kernel;

/**
 *
 * @author Mitchel Strachan <technotheist@gmail.com>
 */
public abstract class BaseRunner extends Kernel implements Runner {
    public static final float MAX_NEG = -Float.MAX_VALUE;
    public static final float MAX_POS = Float.MAX_VALUE;

    protected final int MODE[] = new int[]{0};

    
    protected final int input_size, output_size;
    protected final float[] input;
    protected final float[] output;

    protected BaseRunner(BaseConfig config) {
        this.input_size = config.getInputSize();
        this.output_size = config.getOutputSize();
        this.input = new float[input_size];
        this.output = new float[output_size];
        
        this.setExecutionMode(EXECUTION_MODE.GPU);
        this.setExplicit(true);
        put(MODE);
        put(input);
        put(output);
    }

    @Override
    public final void run() {
        _run(MODE[0]);
    }

    protected void setMode(int i) {
        MODE[0] = i;
        put(MODE);
    }
    
    
    @Override
    public int outputSize() {
        return output_size;
    }

    @Override
    public int inputSize() {
        return input_size;
    }
    
    protected abstract void _run(int mode);
    
    
    
    
    

    /*
     * Built in methods, like static methods
     */
    protected float _sq(float val) {
        return val * val;
    }
    
    protected int _get2D_n(int i, int j, int J) {
        return j + J * i;
    }

    protected int _get2D_i(int n, int J) {
        return n / J;
    }

    protected int _get2D_j(int n, int J) {
        return n % J;
    }

    protected int _get3D_n(int i, int j, int k, int J, int K) {
        return k + K * (_get2D_n(i, j, J));
    }

    protected int _get3D_i(int n, int J, int K) {
        return _get2D_i(n, J * K);
    }

    protected int _get3D_j(int n, int J, int K) {
        return _get2D_j(n / K, J);
    }

    protected int _get3D_k(int n, int K) {
        return n % K;
    }

    protected int _get4D_n(int i, int j, int k, int l, int J, int K, int L) {
        return l + L * (_get3D_n(i, j, k, J, K));
    }

    protected int _get4D_i(int n, int J, int K, int L) {
        return _get3D_i(n, J, K * L);
    }

    protected int _get4D_j(int n, int J, int K, int L) {
        return _get3D_j(n, J, K * L);
    }

    protected int _get4D_k(int n, int K, int L) {
        return _get3D_k(n, K * L);
    }

    protected int _get4D_l(int n, int L) {
        return n % L;
    } 
    
    protected int _get5D_n(int i, int j, int k, int l, int m, int J, int K, int L, int M) {
        return m + M * (_get4D_n(i, j, k, l, J, K, L * M));
    }

    protected int _get5D_i(int n, int J, int K, int L, int M) {
        return _get4D_i(n, J, K, L * M);
    }

    protected int _get5D_j(int n, int J, int K, int L, int M) {
        return _get4D_j(n, J, K, L * M);
    }

    protected int _get5D_k(int n, int K, int L, int M) {
        return _get4D_k(n, K, L * M);
    }

    protected int _get5D_l(int n, int L, int M) {
        return _get4D_l(n, L * M);
    }
    
    protected int _get5D_m(int n, int M) {
        return n % M;
    }
}
